#ifndef __YSIP_H__
#define __YSIP_H__


#include<bits/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/file.h>
#include<string.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#include <iostream>
#include <string>
#include "common/log.h"
#include "common/addon.h"

using namespace std;
typedef __uint32_t uint;


#ifndef __cplusplus
typedef enum bool {false = 0, true = 1} bool;
#endif

#ifndef MAX_NAME_LENGTH
#define MAX_NAME_LENGTH  35
#endif
#define MAX_KEY_LENGTH   20
#define MAX_LINE_LENGTH  256
#define MAX_CODE_LENGTH  20
#define INDEX_KEY_NAME "count"
typedef struct IP_INFO {
	uint minip;
	uint maxip;
	uint region_id;
} IP_INFO;

typedef struct REGION_INFO {
	int id;
	int parent_id;
	int level;
	int center_id;
	char name[MAX_NAME_LENGTH];
	char en_name[MAX_NAME_LENGTH];
} REGION_INFO;

typedef struct REGION_INFO_X {
	int length;
	REGION_INFO info;
	REGION_INFO_X ** childs;
} REGION_INFO_X;

typedef struct REGION_CACHE {
	int id;
	char name[MAX_NAME_LENGTH];
} REGION_CACHE;

bool get_instance();
void release_instance();

bool init_db();

bool bin_search_ip(uint ip, IP_INFO * region_info);

bool check_index();
int get_stat();
static inline int compare_region_info(const void * a, const void * b);
static inline int compare_region_info_en(const void * a, const void * b);

static void free_region_info(REGION_INFO ** region_info, int len);
static void free_region_info_x(REGION_INFO_X * region_info_x);
bool get_ip_info(string ip, REGION_INFO * region_info );
bool get_region_info_by_name(string name, REGION_INFO * region_info);
bool get_region_info_by_en_name(string en_name, REGION_INFO * region_info);
bool get_region_info(int region_id, REGION_INFO * region_info);
REGION_INFO ** get_all_regions(int &len);
REGION_INFO ** get_region_parents(int region_id, int &len);
REGION_INFO_X * get_region_childs(int region_id, int depth);
REGION_INFO ** get_region_info_by_name_ex(string name);
//REGION_INFO ** get_region_info_by_name(string name, int &len, bool is_fuzzy = false);

#ifdef DEBUG
#define DEBUGX(msg) ysip_log("s", msg);
#define DEBUGX2(msg1, msg2) ysip_log("ss", msg1, msg2);
#define DEBUGX3(msg1, msg2, msg3) ysip_log("sss", msg1, msg2, msg3);
#define DEBUGX4(msg1, msg2, msg3, msg4) ysip_log("ssss", msg1, msg2, msg3, msg4);
#define DEBUGX5(msg1, msg2, msg3, msg4, msg5) ysip_log("sssss", msg1, msg2, msg3, msg4, msg5);
#define DEBUGXi(i) ysip_log("dc", i, '\n');
#else
#define DEBUGX(msg)
#define DEBUGX2(msg1, msg2)
#define DEBUGX3(msg1, msg2, msg3)
#define DEBUGX4(msg1, msg2, msg3, msg4)
#define DEBUGX5(msg1, msg2, msg3, msg4, msg5)
#define DEBUGXi(i)
#endif

extern const char * db_file = "/home/anders/dev/cnlion/data/ipdata.db";
extern const char * src_file = "/home/anders/dev/cnlion/data/ipdata.utf8"; 
extern const char * region_file = "/home/anders/dev/cnlion/data/ids.txt";
//extern const char * cache_file = "/home/anders/dev/cnlion/src/data/all.txt";

/* extern const char *db_file = "/home/anders/dev/cnlion/src/data/ipdata.db";
extern const char *src_file = "/home/anders/dev/cnlion/src/data/ipdata.utf8"; */
#if defined(MMAP)
#include "db/mmap.hpp" 
#endif

#endif
